package com.ecb.business.service.impl;

import chainmaker.sdk.demo.ChainConfig;
import com.ecb.business.dto.contract.ExecContractDTO;
import com.ecb.business.dto.contract.QueryContractDTO;
import com.ecb.business.po.ChainAuditPO;
import com.ecb.business.repository.ChainAuditDao;
import com.ecb.business.service.ContractService;
import com.google.protobuf.ByteString;
import lombok.SneakyThrows;
import org.chainmaker.pb.common.ResultOuterClass;
import org.chainmaker.sdk.ChainClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import static chainmaker.sdk.demo.InitClient.chainClient;
import static chainmaker.sdk.demo.InitClient.inItChainClient;
@Service
public class ContractServiceImpl implements ContractService {

    @Autowired
    ChainAuditDao chainAuditDao;
    Map<String, ChainClient> clientMap = new HashMap<>();

    @Override
    @SneakyThrows
    public String getChainConfig(){
        if (chainClient == null){ //需要优化
            inItChainClient();
        }
        return ChainConfig.getChainConfig(chainClient);
    }

    @Override
    @SneakyThrows
    public Map<String, Object> queryContract(QueryContractDTO queryContractDTO) {
        if (chainClient == null){ //需要优化
            inItChainClient();
        }
        ResultOuterClass.TxResponse responseInfo = null;
        Map<String, byte[]> map = new HashMap<>();
        Map<String, Object> queryParams = queryContractDTO.getQueryParams();
        for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
            map.put(entry.getKey(), entry.getValue().toString().getBytes(StandardCharsets.UTF_8));
        }
        try {
            responseInfo = chainClient.queryContract(queryContractDTO.getContractName(), queryContractDTO.getMethod(),
                    null,  map,10000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("查询合约结果：");
        System.out.println(responseInfo.toString());

        // 添加执行记录
        ChainAuditPO chainAuditPO = new ChainAuditPO();
        chainAuditPO.setOperateType("query");
        chainAuditPO.setOperateTarget(queryContractDTO.getContractName());
        chainAuditPO.setDataNew(queryContractDTO.getQueryParams().toString());
        chainAuditDao.save(chainAuditPO);

        long gasUsed = responseInfo.getContractResult().getGasUsed();
        String txId = responseInfo.getTxId();
        ResultOuterClass.ContractResult contractResult = responseInfo.getContractResult();
        ByteString result = contractResult.getResult();
        ResultOuterClass.TxStatusCode code = responseInfo.getCode();


        Map<String, Object> resMap = new HashMap<>();
        resMap.put("gasUsed", gasUsed);
        resMap.put("txId", txId);
        resMap.put("code", code);
        resMap.put("result", result.toString(StandardCharsets.UTF_8));

        return resMap;
    }

    @Override
    @SneakyThrows
    public Map<String, Object> execContract(ExecContractDTO execContractDTO) {
        if (chainClient == null){ //需要优化
            inItChainClient();
        }
        ResultOuterClass.TxResponse responseInfo = null;

        Map<String, byte[]> map = new HashMap<>();
        Map<String, Object> queryParams = execContractDTO.getExecParams();
        for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
            map.put(entry.getKey(), entry.getValue().toString().getBytes(StandardCharsets.UTF_8));
        }

        try {
            responseInfo = chainClient.invokeContract(execContractDTO.getContractName(), execContractDTO.getMethod(),
                    null, map,10000, 10000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("执行合约结果：");
        System.out.println(responseInfo);

        // 添加执行记录
        ChainAuditPO chainAuditPO = new ChainAuditPO();
        chainAuditPO.setOperateType("exec");
        chainAuditPO.setOperateTarget(execContractDTO.getContractName());
        chainAuditPO.setDataNew(execContractDTO.getExecParams().toString());
        chainAuditDao.save(chainAuditPO);

        long gasUsed = responseInfo.getContractResult().getGasUsed();
        String txId = responseInfo.getTxId();
        ResultOuterClass.ContractResult contractResult = responseInfo.getContractResult();
        ByteString result = contractResult.getResult();
        ResultOuterClass.TxStatusCode code = responseInfo.getCode();


        Map<String, Object> resMap = new HashMap<>();
        resMap.put("gasUsed", gasUsed);
        resMap.put("txId", txId);
        resMap.put("code", code);
        resMap.put("result", result.toString(StandardCharsets.UTF_8));
        return resMap;
    }


}
